//+------------------------------------------------------------------+
//|                                                    Logger.mqh    |
//|                                    Copyright 2024, Precision EA  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Precision EA"
#property strict

enum ENUM_LOG_LEVEL {
    LOG_LEVEL_DEBUG,
    LOG_LEVEL_INFO, 
    LOG_LEVEL_WARN,
    LOG_LEVEL_ERROR,
    LOG_LEVEL_CRITICAL
};

class Logger {
private:
    static string m_log_path;
    static bool m_enable_file_logging;
    static bool m_enable_terminal_logging;
    static ENUM_LOG_LEVEL m_min_level;
    static int m_max_file_size_mb;
    
    static string GetLevelString(ENUM_LOG_LEVEL level) {
        switch(level) {
            case LOG_LEVEL_DEBUG: return "DEBUG";
            case LOG_LEVEL_INFO: return "INFO";
            case LOG_LEVEL_WARN: return "WARN";
            case LOG_LEVEL_ERROR: return "ERROR";
            case LOG_LEVEL_CRITICAL: return "CRITICAL";
            default: return "UNKNOWN";
        }
    }
    
    static string GetColorCode(ENUM_LOG_LEVEL level) {
        switch(level) {
            case LOG_LEVEL_DEBUG: return "94"; // Blue
            case LOG_LEVEL_INFO: return "92"; // Green
            case LOG_LEVEL_WARN: return "93"; // Yellow
            case LOG_LEVEL_ERROR: return "91"; // Red
            case LOG_LEVEL_CRITICAL: return "95"; // Magenta
            default: return "97"; // White
        }
    }
    
    static void RotateLogFile() {
        if(!m_enable_file_logging) return;
        
        int handle = FileOpen(m_log_path, FILE_READ|FILE_BIN);
        if(handle != INVALID_HANDLE) {
            ulong size = FileSize(handle);
            FileClose(handle);
            
            if(size > m_max_file_size_mb * 1024 * 1024) {
                string new_path = m_log_path + "." + TimeToString(TimeCurrent(), TIME_DATE);
                if(FileMove(m_log_path, 0, new_path, FILE_REWRITE)) {
                    FileDelete(m_log_path);
                }
            }
        }
    }
    
    static void WriteToFile(string message) {
        if(!m_enable_file_logging) return;
        
        RotateLogFile();
        
        int handle = FileOpen(m_log_path, FILE_READ|FILE_WRITE|FILE_TXT|FILE_ANSI, 0, CP_UTF8);
        if(handle != INVALID_HANDLE) {
            FileSeek(handle, 0, SEEK_END);
            FileWrite(handle, message);
            FileClose(handle);
        }
    }

public:
    static void Initialize(string symbol = "", 
                          ENUM_LOG_LEVEL min_level = LOG_LEVEL_INFO,
                          bool enable_file = true,
                          bool enable_terminal = true,
                          int max_file_size_mb = 10) {
        m_min_level = min_level;
        m_enable_file_logging = enable_file;
        m_enable_terminal_logging = enable_terminal;
        m_max_file_size_mb = max_file_size_mb;
        
        if(m_enable_file_logging) {
            string date_str = TimeToString(TimeCurrent(), TIME_DATE);
            string account = IntegerToString(AccountInfoInteger(ACCOUNT_LOGIN));
            m_log_path = "Logs/" + account + "_" + symbol + "_" + date_str + ".log";
            
            // Create directory if it doesn't exist
            if(!FileIsExist("Logs")) {
                FolderCreate("Logs");
            }
        }
        
        Info("Logger initialized", "SYSTEM");
    }
    
    static void Log(string message, 
                   string module = "", 
                   ENUM_LOG_LEVEL level = LOG_LEVEL_INFO,
                   int error_code = 0) {
        
        if(level < m_min_level) return;
        
        string timestamp = TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS);
        string level_str = GetLevelString(level);
        string color_code = GetColorCode(level);
        
        string formatted_msg = StringFormat("%s [%s]", timestamp, level_str);
        if(module != "") formatted_msg += StringFormat(" [%s]", module);
        if(error_code != 0) formatted_msg += StringFormat(" [ERR:%d]", error_code);
        formatted_msg += " " + message;
        
        // Terminal output
        if(m_enable_terminal_logging) {
            string colored_msg = StringFormat("\x1B[%sm%s\x1B[0m", color_code, formatted_msg);
            Print(colored_msg);
        }
        
        // File output (uncolored)
        if(m_enable_file_logging) {
            WriteToFile(formatted_msg);
        }
        
        // Alert for critical errors
        if(level == LOG_LEVEL_CRITICAL) {
            Alert(formatted_msg);
        }
    }
    
    static void Debug(string message, string module = "") {
        Log(message, module, LOG_LEVEL_DEBUG);
    }
    
    static void Info(string message, string module = "") {
        Log(message, module, LOG_LEVEL_INFO);
    }
    
    static void Warn(string message, string module = "") {
        Log(message, module, LOG_LEVEL_WARN);
    }
    
    static void Error(string message, string module = "", int error_code = 0) {
        Log(message, module, LOG_LEVEL_ERROR, error_code);
    }
    
    static void Critical(string message, string module = "", int error_code = 0) {
        Log(message, module, LOG_LEVEL_CRITICAL, error_code);
    }
    
    static void SetMinLevel(ENUM_LOG_LEVEL level) {
        m_min_level = level;
        Info(StringFormat("Log level changed to %s", GetLevelString(level)), "SYSTEM");
    }
    
    static string GetLogPath() {
        return m_log_path;
    }
};

static string Logger::m_log_path = "";
static bool Logger::m_enable_file_logging = true;
static bool Logger::m_enable_terminal_logging = true;
static ENUM_LOG_LEVEL Logger::m_min_level = LOG_LEVEL_INFO;
static int Logger::m_max_file_size_mb = 10;